package org.amos.server.modules.upms.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.amos.core.basic.annotation.Log;
import org.amos.core.basic.constant.SystemConstant;
import org.amos.core.basic.exception.ServiceException;
import org.amos.core.basic.utils.AmosUtils;
import org.amos.core.basic.utils.JsonUtils;
import org.amos.core.frame.utils.RedisUtils;
import org.amos.msg.enums.MsgPlatformEnum;
import org.amos.msg.platform.AbstractMsgPlatform;
import org.amos.msg.platform.MsgPlatform;
import org.amos.msg.platform.MsgPlatformConfig;
import org.amos.msg.platform.MsgPlatformManager;
import org.amos.server.modules.upms.dto.ConfigMsgDTO;
import org.amos.server.modules.upms.entity.ConfigMsg;
import org.amos.server.modules.upms.mapper.ConfigMsgMapper;
import org.amos.server.modules.upms.service.IConfigMsgService;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.amos.server.constant.SysCacheConstant.SYS_CACHE_FORMAT;
import static org.amos.server.constant.SysCacheConstant.SYS_CONFIG_MAIL_KEY;

@Service
@RequiredArgsConstructor
public class ConfigMsgServiceImpl extends ServiceImpl<ConfigMsgMapper, ConfigMsg> implements IConfigMsgService {

    private final RedisUtils redisUtils;

    private final MsgPlatformManager platformManager;

    @Override
    public MsgPlatform getDefaultPlatform(Integer msgType) {
        ConfigMsg defaultConfig = getDefaultConfig(msgType);
        if (Objects.nonNull(defaultConfig)) {
            MsgPlatformEnum platform = MsgPlatformEnum.getByPlatform(defaultConfig.getPlatform(), msgType);
            MsgPlatformConfig msgPlatformConfig = parseConfig(defaultConfig.getPlatform(), defaultConfig.getType(), defaultConfig.getConfig());
            AbstractMsgPlatform<MsgPlatformConfig> msgPlatform = platformManager.getPlatform(defaultConfig.getNo(), platform.getCode(), msgPlatformConfig);
            return msgPlatform;
        }
        return null;
    }

    @Override
    public ConfigMsg findById(Long id) {
        return super.getById(id);
    }

    @Override
    public ConfigMsg getDefaultConfig(Integer msgType) {
        Assert.state(Objects.nonNull(msgType), "msgType cannot null");
        QueryWrapper<ConfigMsg> qw = new QueryWrapper();
        qw.eq(AmosUtils.toDbField(ConfigMsg::getType), msgType);
        qw.eq(AmosUtils.toDbField(ConfigMsg::getIsDefault), SystemConstant.SYS_EFFECTIVE_STATUS);
        return super.getOne(qw);
    }

    @Override
    public ConfigMsg getConfigByNo(String configNo) {
        QueryWrapper<ConfigMsg> qw = new QueryWrapper();
        qw.eq(AmosUtils.toDbField(ConfigMsg::getNo), configNo);
        return super.getOne(qw);
    }

    @Override
    @Log(value = "[更新消息配置]")
    public Boolean saveOrUpdateConfig(ConfigMsgDTO dto) {
        ConfigMsg entity = AmosUtils.copy(dto, ConfigMsg.class);
        // 校验配置信息合法性
        validateConfig(dto.getPlatform(), dto.getType(), dto.getConfig());
        entity.setConfig(JsonUtils.objectToJson(dto.getConfig()));
        // 新增检查配置编码
        if (StrUtil.isNotBlank(entity.getNo())) {
            QueryWrapper<ConfigMsg> qw = new QueryWrapper();
            if (Objects.nonNull(entity.getId())) {
                qw.ne(AmosUtils.toDbField(ConfigMsg::getId), entity.getId());
            }
            qw.eq(AmosUtils.toDbField(ConfigMsg::getNo), entity.getNo());
            qw.eq(AmosUtils.toDbField(ConfigMsg::getType), entity.getType());
            long count = super.count(qw);

            if (count > 0) {
                throw new ServiceException("配置编码已存在,请勿重复添加!");
            }
        }
        if (SystemConstant.SYS_EFFECTIVE_STATUS.equals(entity.getIsDefault())) {
            QueryWrapper<ConfigMsg> qw = new QueryWrapper();
            if (Objects.nonNull(entity.getId())) {
                qw.ne(AmosUtils.toDbField(ConfigMsg::getId), entity.getId());
            }
            qw.eq(AmosUtils.toDbField(ConfigMsg::getIsDefault), SystemConstant.SYS_EFFECTIVE_STATUS);
            long count = super.count(qw);

            if (count > 0) {
                throw new ServiceException("默认配置已存在,请勿重复添加!");
            }
        }
        return super.saveOrUpdate(entity);
    }

    @Override
    @Log(value = "[删除短信配置]")
    public Boolean remove(Set<Long> ids) {
        QueryWrapper<ConfigMsg> qw = new QueryWrapper();
        qw.in(AmosUtils.toDbField(ConfigMsg::getId), ids);
        List<ConfigMsg> list = super.list(qw);
        // 删除数据库信息
        UpdateWrapper<ConfigMsg> uw = new UpdateWrapper<>();
        uw.in(AmosUtils.toDbField(ConfigMsg::getId), ids).set(AmosUtils.toDbField(ConfigMsg::getIsDeleted), SystemConstant.SYS_DELETE_FLAG_ALREADY);
        super.update(uw);
        // 删除redis信息
        List<String> noList = list.stream().map(entity -> String.format(SYS_CONFIG_MAIL_KEY + SYS_CACHE_FORMAT, entity.getNo())).collect(Collectors.toList());
        List<String> keyList = ids.stream().map(id -> String.format(SYS_CONFIG_MAIL_KEY + SYS_CACHE_FORMAT, id)).collect(Collectors.toList());
        keyList.addAll(noList);
        redisUtils.del(keyList.toArray(new String[]{}));
        return Boolean.TRUE;
    }
    /**
     * 校验配置信息是否合法
     * @param platform
     * @param config
     * @return
     */
    private void validateConfig(Integer platform, Integer type, Map<String, Object> config) {
        Class<? extends MsgPlatformConfig> configClass = MsgPlatformEnum.getByPlatform(platform, type).getConfigClass();
        MsgPlatformConfig platformConfig = JsonUtils.jsonToPojo(JsonUtils.objectToJson(config), configClass);
        Assert.state(Objects.nonNull(platformConfig), "config is Illegal param");
    }
    /**
     * 将json字符串配置信息转换成对应文件存储平台
     * @param platform
     * @param config
     * @return
     */
    private MsgPlatformConfig parseConfig(Integer platform, Integer type, String config) {
        Class<? extends MsgPlatformConfig> configClass = MsgPlatformEnum.getByPlatform(platform, type).getConfigClass();
        MsgPlatformConfig platformConfig = JsonUtils.jsonToPojo(config, configClass);
        Assert.state(Objects.nonNull(platformConfig), "config is Illegal param");
        return platformConfig;
    }
}